package cn.meike.net.protocol
{
	import flash.utils.ByteArray;

	public class KylinMsg
	{
		static public const BASEVERSION : uint = 1;
		static public const CURRVERSION : uint = 2;
		static public const VERSION_m_stMsgHead : uint = 1;
		static public const VERSION_m_stMsgBody : uint = 1;
		
		public var m_stMsgHead : MsgHead;
		public var m_stMsgBody : MsgBody;
		
		public function KylinMsg()
		{
			m_stMsgHead = new MsgHead();
			m_stMsgBody = new MsgBody();
		}
		
		public function encode(buf:ByteArray, cutVersion:uint = 0):int 
		{
			if (cutVersion == 0 || cutVersion > CURRVERSION) {
				cutVersion = CURRVERSION;
			}
			
			//整条协议的开始位置
			const savedBufBeginPos : uint = buf.position;
			
			var ret : int = ErrorMap.NO_ERROR;
			
			if (VERSION_m_stMsgHead <= cutVersion) {
				if (m_stMsgHead == null) {
					return ErrorMap.ERR_REFERENCE_IS_NULL;
				}
				//将头信息写入缓冲区
				ret = m_stMsgHead.encode(buf, cutVersion);
				if (ret != ErrorMap.NO_ERROR) {
					return ret;
				}
			}
			
			if (VERSION_m_stMsgBody <= cutVersion) {
				
				//获得该协议的 协议ID
				const m_stMsgBodySelect : int = m_stMsgHead.m_uiMsgID;
					
				//该位置是用于描述 消息体 长度的
				const m_stMsgBodySizeInfoPos : uint = savedBufBeginPos + 22;
				
				//该位置是真正消息体开始的位置 
				var m_stMsgBodyBeginPos : uint = buf.position;
				
				if (m_stMsgBody == null) {
					return ErrorMap.ERR_REFERENCE_IS_NULL;
				}
				ret = m_stMsgBody.encode(m_stMsgBodySelect, buf, cutVersion);
				if (ret != ErrorMap.NO_ERROR) {
					return ret;
				}
				//当把 消息体 完全写入成功的时候才知道其真正的长度,这时候需要在重新在消息头 m_uiBodyLength字段对应的数据
				TdrUtil.directWriteUint(buf, m_stMsgBodySizeInfoPos, buf.position - m_stMsgBodyBeginPos);
			}
			
			
			return 0;
		}
		
		public function decode(buf:ByteArray, cutVersion:uint = 0):int 
		{
			if (cutVersion == 0 || cutVersion > CURRVERSION) {
				cutVersion = CURRVERSION;
			}
			
			const savedBufBeginPos : uint = buf.position;
			
			// get versionindicator
			if (buf.bytesAvailable < 2) {
				return ErrorMap.ERR_PARTIAL_MSG;
			}
			// get cutVersion-value
			cutVersion = TdrUtil.directReadSmalluint(buf, buf.position + 0);
			if (BASEVERSION > cutVersion || cutVersion > CURRVERSION) {
				return ErrorMap.ERR_INVALIED_CUTOFF_VERSION;
			}
			
			var ret : int = ErrorMap.NO_ERROR;
			
			// decode entries
			if (VERSION_m_stMsgHead <= cutVersion) {
				if (m_stMsgHead == null) {
					return ErrorMap.ERR_REFERENCE_IS_NULL;
				}
				ret = m_stMsgHead.decode(buf, cutVersion);
				if (ret != ErrorMap.NO_ERROR) {
					return ret;
				}
			}
			
			if (VERSION_m_stMsgBody <= cutVersion) {
				const m_stMsgBodySelect : int = m_stMsgHead.m_uiMsgID;
				// get entry's sizeinfo
				const m_stMsgBodySize : uint = TdrUtil.directReadUint(buf, savedBufBeginPos + 22);
				if (m_stMsgBodySize > buf.bytesAvailable) {
					return ErrorMap.ERR_PARTIAL_MSG;
				}
				if (m_stMsgBody == null) {
					return ErrorMap.ERR_REFERENCE_IS_NULL;
				}
				ret = m_stMsgBody.decode(m_stMsgBodySelect, buf, cutVersion);
				if (ret != ErrorMap.NO_ERROR) {
					return ret;
				}
			}
			
			return ret;
		}
	}
}



